{
 "cells": [
  {
   "cell_type": "markdown",
   "source": [
    "## hasattr()函数\n",
    "hasattr() 函数用来判断某个类实例对象是否包含指定名称的属性或方法。该函数的语法格式如下：\n",
    "> hasattr(obj, name)\n",
    "\n",
    "其中 obj 指的是某个类的实例对象，name 表示指定的属性名或方法名。同时，该函数会将判断的结果（True 或者 False）作为返回值反馈回来。"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hello, pangyazhou\n",
      "True\n",
      "True\n",
      "False\n"
     ]
    }
   ],
   "source": [
    "class Person(object):\n",
    "    def __init__(self):\n",
    "        self.name = 'pangyazhou'\n",
    "        self.age = 34\n",
    "    def say(self):\n",
    "        print('hello,', self.name)\n",
    "\n",
    "person = Person()\n",
    "person.say()\n",
    "print(hasattr(person, 'say'))\n",
    "print(hasattr(person, 'name'))\n",
    "print(hasattr(person, 'address'))"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## getattr() 函数\n",
    "getattr() 函数获取某个类实例对象中指定属性的值。和 hasattr() 函数不同，该函数只会从类对象包含的所有属性中进行查找。\n",
    "getattr() 函数的语法格式如下：\n",
    "> getattr(obj, name[, default])\n",
    "\n",
    "其中，obj 表示指定的类实例对象，name 表示指定的属性名，而 default 是可选参数，用于设定该函数的默认返回值，即当函数查找失败时，如果不指定 default 参数，则程序将直接报 AttributeError 错误，反之该函数将返回 default 指定的值。\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hello, pangyazhou\n",
      "pangyazhou\n",
      "<bound method Person.say of <__main__.Person object at 0x000001B6455A65F0>>\n",
      "hefei\n"
     ]
    },
    {
     "ename": "AttributeError",
     "evalue": "'Person' object has no attribute 'address'",
     "output_type": "error",
     "traceback": [
      "\u001B[1;31m---------------------------------------------------------------------------\u001B[0m",
      "\u001B[1;31mAttributeError\u001B[0m                            Traceback (most recent call last)",
      "Cell \u001B[1;32mIn[12], line 14\u001B[0m\n\u001B[0;32m     12\u001B[0m \u001B[38;5;28mprint\u001B[39m(\u001B[38;5;28mgetattr\u001B[39m(person, \u001B[38;5;124m'\u001B[39m\u001B[38;5;124msay\u001B[39m\u001B[38;5;124m'\u001B[39m))\n\u001B[0;32m     13\u001B[0m \u001B[38;5;28mprint\u001B[39m(\u001B[38;5;28mgetattr\u001B[39m(person, \u001B[38;5;124m'\u001B[39m\u001B[38;5;124maddress\u001B[39m\u001B[38;5;124m'\u001B[39m, \u001B[38;5;124m'\u001B[39m\u001B[38;5;124mhefei\u001B[39m\u001B[38;5;124m'\u001B[39m))\n\u001B[1;32m---> 14\u001B[0m \u001B[38;5;28mprint\u001B[39m(\u001B[38;5;28;43mgetattr\u001B[39;49m\u001B[43m(\u001B[49m\u001B[43mperson\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;124;43m'\u001B[39;49m\u001B[38;5;124;43maddress\u001B[39;49m\u001B[38;5;124;43m'\u001B[39;49m\u001B[43m)\u001B[49m)\n",
      "\u001B[1;31mAttributeError\u001B[0m: 'Person' object has no attribute 'address'"
     ]
    }
   ],
   "source": [
    "class Person(object):\n",
    "    def __init__(self):\n",
    "        self.name = 'pangyazhou'\n",
    "        self.age = 34\n",
    "    def say(self):\n",
    "        print('hello,', self.name)\n",
    "\n",
    "person = Person()\n",
    "person.say()\n",
    "\n",
    "print(getattr(person, 'name'))\n",
    "print(getattr(person, 'say'))\n",
    "print(getattr(person, 'address', 'hefei'))\n",
    "print(getattr(person, 'address'))"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "##  setattr()函数\n",
    "最基础的功能是修改类实例对象中的属性值。其次，它还可以实现为实例对象动态添加属性或者方法。\n",
    "setattr() 函数的语法格式如下：\n",
    "> setattr(obj, name, value)\n",
    "\n",
    "下面例子演示如何通过该函数修改某个类实例对象的属性值："
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hello, pangyazhou\n",
      "pangyazhou\n",
      "34\n",
      "lixiaolong\n",
      "hello, lixiaolong\n",
      "go go go...\n",
      "go go go...\n"
     ]
    }
   ],
   "source": [
    "def go(self):\n",
    "    print('go go go...')\n",
    "\n",
    "class Person(object):\n",
    "    def __init__(self):\n",
    "        self.name = 'pangyazhou'\n",
    "        self.age = 34\n",
    "    def say(self):\n",
    "        print('hello,', self.name)\n",
    "\n",
    "person = Person()\n",
    "person.say()\n",
    "\n",
    "print(person.name)\n",
    "print(person.age)\n",
    "setattr(person, 'name', 'lixiaolong')\n",
    "print(person.name)\n",
    "person.say()\n",
    "# 将外部方法go赋予属性name\n",
    "setattr(person, 'name', go)\n",
    "person.name(person)\n",
    "# 给予不存在属性赋值，动态添加指定名称的属性或方法\n",
    "setattr(person, 'go', go)\n",
    "person.go(person)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}